﻿using System;
using System.Collections.Generic;
using System.Linq;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Revit;
using YArchitech.Revit.RevitExtension;

namespace YArchitech.MEP.Electric.CableLay
{
	public class CableLookUp
	{
		public CableLookUp(UIDocument uiDoc, string layPathIds)
		{
			this.m_uiDoc = uiDoc;
			this.m_doc = uiDoc.ActiveView.Document;
			string[] array = layPathIds.Trim().Split(CableLookUp.m_sp, StringSplitOptions.RemoveEmptyEntries);
			this.m_lstEntId = new List<ElementId>();
			for (int i = 0; i < array.Length; i++)
			{
				ElementId item = new ElementId(Convert.ToInt32(array[i]));
				this.m_lstEntId.Add(item);
			}
		}

		public void LookUp()
		{
			if (this.m_doc == null || this.m_lstEntId == null || this.m_lstEntId.Count <= 0)
			{
				return;
			}
			List<XYZ> vertex = this.GetVertex(null, this.m_lstEntId[0]);
			List<XYZ> vertex2 = this.GetVertex(this.m_lstEntId.Last<ElementId>(), null);
			List<XYZ> list = new List<XYZ>();
			ElementId elementId = this.m_lstEntId[0];
			for (int i = 1; i < this.m_lstEntId.Count; i++)
			{
				ElementId firstID = elementId;
				elementId = this.m_lstEntId[i];
				List<XYZ> vertex3 = this.GetVertex(firstID, elementId);
				if (vertex3 != null)
				{
					foreach (XYZ item in vertex3)
					{
						list.Add(item);
					}
				}
			}
			if (list.Count <= 0)
			{
				list = vertex;
			}
			else
			{
				XYZ pt = list[0];
				XYZ farthestPoint = this.GetFarthestPoint(pt, vertex);
				if (farthestPoint != null)
				{
					list.Insert(0, farthestPoint);
				}
				pt = list.Last<XYZ>();
				farthestPoint = this.GetFarthestPoint(pt, vertex2);
				if (farthestPoint != null)
				{
					list.Add(farthestPoint);
				}
			}
			this.EliminateOverlapPoint(ref list);
			Transaction transaction = new Transaction(this.m_doc, "CableLookUp");
			transaction.Start();
			List<ElementId> list2 = new List<ElementId>();
			XYZ pt2 = list[0];
			for (int j = 1; j < list.Count; j++)
			{
				XYZ xyz = list[j];
				ModelCurve modelCurve = this.DrawModelLine(this.m_doc, pt2, xyz);
				pt2 = xyz;
				if (modelCurve != null)
				{
					list2.Add(modelCurve.Id);
				}
			}
			transaction.Commit();
			if (list2.Count <= 0)
			{
				return;
			}
            Autodesk.Revit.DB.View view = CableLayRevitCommon.Get3DView(this.m_uiDoc);
			if (view == null)
			{
				return;
			}
			this.m_uiDoc.ActiveView = view;
			this.SetElementFillColor(view, list2);
			HYTwinkle hytwinkle = new HYTwinkle();
			hytwinkle.TwinkleInterval = 1000;
			hytwinkle.View = view;
			hytwinkle.Ids = list2;
			hytwinkle.Start();
			try
			{
				this.m_uiDoc.Selection.PickPoint("按Esc或点击左键退出查看。");
			}
			finally
			{
				hytwinkle.Stop();
				hytwinkle.Dispose();
				transaction = new Transaction(this.m_doc, "CableLookUp Delete Model Line");
				transaction.Start();
				this.m_doc.Delete(list2);
				transaction.Commit();
			}
		}

		private List<XYZ> GetVertex(ElementId firstID, ElementId secondID)
		{
			if (null == firstID && null == secondID)
			{
				return null;
			}
			MEPCurve mepcurve = null;
			MEPCurve mepcurve2 = null;
			if (null != firstID)
			{
				Element element = this.m_doc.GetElement(firstID);
				mepcurve = ((element == null) ? null : (element as MEPCurve));
			}
			if (null != secondID)
			{
				Element element2 = this.m_doc.GetElement(secondID);
				mepcurve2 = ((element2 == null) ? null : (element2 as MEPCurve));
			}
			if (mepcurve == null && mepcurve2 == null)
			{
				return null;
			}
			List<XYZ> list = new List<XYZ>();
			XYZ endPoint;
			XYZ endPoint2;
			if (mepcurve == null && mepcurve2 != null)
			{
				Curve curve = (mepcurve2.Location as LocationCurve).Curve;
				endPoint = curve.GetEndPoint(0);
				endPoint2 = curve.GetEndPoint(1);
				list.Add(endPoint);
				list.Add(endPoint2);
				return list;
			}
			if (mepcurve != null && mepcurve2 == null)
			{
				Curve curve2 = (mepcurve.Location as LocationCurve).Curve;
				endPoint = curve2.GetEndPoint(0);
				endPoint2 = curve2.GetEndPoint(1);
				list.Add(endPoint);
				list.Add(endPoint2);
				return list;
			}
			Curve curve3 = (mepcurve.Location as LocationCurve).Curve;
			endPoint = curve3.GetEndPoint(0);
			endPoint2 = curve3.GetEndPoint(1);
			Curve curve4 = (mepcurve2.Location as LocationCurve).Curve;
			XYZ endPoint3 = curve4.GetEndPoint(0);
			XYZ endPoint4 = curve4.GetEndPoint(1);
			return this.Intersect(endPoint, endPoint2, endPoint3, endPoint4);
		}

		private List<XYZ> Intersect(XYZ pt0, XYZ pt1, XYZ ptEx0, XYZ ptEx1)
		{
			Line line = YJKLineEx.YJKGetBound(pt0, pt1);
			Line line2 = YJKLineEx.YJKGetBound(ptEx0, ptEx1);
			List<XYZ> list = new List<XYZ>();
			if (this.IsParallel(line, line2))
			{
				IntersectionResult intersectionResult = line.Project(ptEx0);
				if (intersectionResult != null)
				{
					XYZ item = intersectionResult.XYZPoint;
					list.Add(item);
				}
				IntersectionResult intersectionResult2 = line2.Project(pt0);
				if (intersectionResult2 != null)
				{
					XYZ item = intersectionResult2.XYZPoint;
					list.Add(item);
				}
				return list;
			}
			line.MakeUnbound();
			line2.MakeUnbound();
			IntersectionResultArray intersectionResultArray = new IntersectionResultArray();
			SetComparisonResult setComparisonResult = line.Intersect(line2, out intersectionResultArray);
			if (4 != (int)setComparisonResult && intersectionResultArray != null && !intersectionResultArray.IsEmpty)
			{
				XYZ item = intersectionResultArray.get_Item(0).XYZPoint;
				list.Add(item);
				return list;
			}
			if (list.Count <= 0)
			{
				XYZ item = YJKRevitTools.GetDLineP(ptEx0, ptEx1, pt0, pt1);
				list.Add(item);
				item = YJKRevitTools.GetDLineP(pt0, pt1, ptEx0, ptEx1);
				list.Add(item);
				return list;
			}
			return list;
		}

		private bool IsParallel(Line line, Line lineEx)
		{
			XYZ xyz = line.GetEndPoint(1) - line.GetEndPoint(0);
			XYZ xyz2 = lineEx.GetEndPoint(1) - lineEx.GetEndPoint(0);
			double num = xyz.AngleTo(xyz2);
			return Math.Abs(num - Math.PI) < 0.0001 || num < 0.0001;
		}

		private XYZ GetNearestPoint(XYZ pt, List<XYZ> points)
		{
			if (pt == null || points.Count <= 0)
			{
				return null;
			}
			XYZ xyz = points[0];
			double num = pt.DistanceTo(xyz);
			foreach (XYZ xyz2 in points)
			{
				double num2 = pt.DistanceTo(xyz2);
				if (num2 < num)
				{
					xyz = xyz2;
					num = num2;
				}
			}
			return xyz;
		}

		private XYZ GetFarthestPoint(XYZ pt, List<XYZ> points)
		{
			if (pt == null || points == null || points.Count <= 0)
			{
				return null;
			}
			XYZ result = null;
			double num = -1.0;
			foreach (XYZ xyz in points)
			{
				double num2 = pt.DistanceTo(xyz);
				if (num < num2)
				{
					result = xyz;
					num = num2;
				}
			}
			return result;
		}

		private void EliminateOverlapPoint(ref List<XYZ> vertexSet)
		{
			if (vertexSet == null || vertexSet.Count <= 1)
			{
				return;
			}
			XYZ xyz = vertexSet[0];
			for (int i = 1; i < vertexSet.Count; i++)
			{
				XYZ xyz2 = vertexSet[i];
				if (xyz2.DistanceTo(xyz) <= 0.1)
				{
					vertexSet.Remove(xyz);
					this.EliminateOverlapPoint(ref vertexSet);
					return;
				}
				xyz = xyz2;
			}
		}

		private ModelCurve DrawModelLine(Document doc, XYZ pt, XYZ ptEx)
		{
			if (doc == null || pt == null || ptEx == null)
			{
				return null;
			}
			ModelCurve result;
			try
			{
				Plane plane = RevitVersionFuncs.CreatePlanByNormalAndOrigin(ptEx.CrossProduct(pt), pt);
				SketchPlane sketchPlane = RevitVersionFuncs.NewSketchPlane(doc, plane);
				result = doc.Create.NewModelCurve(YJKLineEx.YJKGetBound(pt, ptEx), sketchPlane);
			}
			catch
			{
				result = null;
			}
			return result;
		}

		private Connector TravelingPathEx(MEPCurve curve, ElementId connectId, ref List<ElementId> lstElement)
		{
			if (curve == null || null == connectId)
			{
				return null;
			}
			ConnectorSet connectors = curve.ConnectorManager.Connectors;
			if (connectors.Size <= 0)
			{
				return null;
			}
			foreach (object obj in connectors)
			{
				Connector connector = (Connector)obj;
				if (connector.IsConnected)
				{
					foreach (object obj2 in connector.AllRefs)
					{
						Connector connector2 = (Connector)obj2;
						if (connector2.IsConnected)
						{
							Element owner = connector2.Owner;
							ElementId id = owner.Id;
							if (id == connectId)
							{
								return connector2;
							}
							if (!lstElement.Contains(id))
							{
								lstElement.Add(id);
								Connector connector3 = null;
								if (owner is FamilyInstance)
								{
									FamilyInstance family = owner as FamilyInstance;
									connector3 = this.TravelingPathEx(family, connectId, ref lstElement);
								}
								else if (owner is MEPCurve)
								{
									MEPCurve curve2 = owner as MEPCurve;
									connector3 = this.TravelingPathEx(curve2, connectId, ref lstElement);
								}
								if (connector3 != null)
								{
									return connector3;
								}
							}
						}
					}
				}
			}
			return null;
		}

		private Connector TravelingPathEx(FamilyInstance family, ElementId connectId, ref List<ElementId> lstElement)
		{
			if (family == null || null == connectId)
			{
				return null;
			}
			ConnectorSet connectors = family.MEPModel.ConnectorManager.Connectors;
			if (connectors.Size <= 0)
			{
				return null;
			}
			foreach (object obj in connectors)
			{
				Connector connector = (Connector)obj;
				if (connector.IsConnected)
				{
					foreach (object obj2 in connector.AllRefs)
					{
						Connector connector2 = (Connector)obj2;
						if (connector2.IsConnected)
						{
							Element owner = connector2.Owner;
							ElementId id = owner.Id;
							if (id == connectId)
							{
								return connector2;
							}
							if (!lstElement.Contains(id))
							{
								lstElement.Add(id);
								Connector connector3 = null;
								if (owner is FamilyInstance)
								{
									FamilyInstance family2 = owner as FamilyInstance;
									connector3 = this.TravelingPathEx(family2, connectId, ref lstElement);
								}
								else if (owner is MEPCurve)
								{
									MEPCurve curve = owner as MEPCurve;
									connector3 = this.TravelingPathEx(curve, connectId, ref lstElement);
								}
								if (connector3 != null)
								{
									return connector3;
								}
							}
						}
					}
				}
			}
			return null;
		}

		public void SetElementFillColor(View view, ICollection<ElementId> Ids)
		{
			if (view == null || Ids == null || Ids.Count <= 0)
			{
				return;
			}
			Transaction transaction = new Transaction(this.m_doc, "CableLookUp Set Model Line Color");
			transaction.Start();
			try
			{
				view.SetYJKProjColorOverrideByElement(Ids, new Color(byte.MaxValue, 0, 0));
				transaction.Commit();
			}
			catch (Exception)
			{
				if (transaction != null && (int)transaction.GetStatus() != 3)
				{
					transaction.RollBack();
				}
			}
		}

		private static char[] m_sp = new char[]
		{
			','
		};

		private UIDocument m_uiDoc;

		private Document m_doc;

		private List<ElementId> m_lstEntId;
	}
}
